package cn.starlightsoftware.sherly.service.file;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.starlightsoftware.sherly.controller.admin.file.vo.*;
import io.minio.*;
import io.minio.http.Method;
import lombok.SneakyThrows;
import cn.starlightsoftware.sherly.config.MinioConfig;
import cn.starlightsoftware.sherly.db.mysql.file.FileMapper;
import cn.starlightsoftware.sherly.db.model.file.FileDO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.concurrent.TimeUnit;

/**
 * @author 谷子毅
 * @date 2024/5/27
 */
@Service
public class FileServiceImpl implements FileService {

    @Resource
    private MinioConfig minioConfig;

    @Resource
    private MinioClient minioClient;

    @Resource
    private FileMapper fileMapper;

    @Override
    @SneakyThrows
    public FileUploadRespVO upload(MultipartFile file, String path) {

        String finalName = IdUtil.randomUUID() + "." + FileUtil.getSuffix(file.getOriginalFilename());
        String finalPath = path + "/" + DateUtil.today() + "/" + finalName;

        minioClient.putObject(
                PutObjectArgs
                        .builder()
                        .bucket(minioConfig.getBucketName())
                        .object(finalPath)
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .build()
        );

        fileMapper.insert(new FileDO()
                .setOriginalName(file.getOriginalFilename())
                .setPath(finalPath)
                .setUrl(minioConfig.getStaticDomain() + finalPath)
                .setSuffix(FileUtil.getSuffix(file.getOriginalFilename()))
                .setSize(file.getSize())
        );

        return new FileUploadRespVO()
                .setAccessUrl(minioConfig.getStaticDomain() + minioConfig.getBucketName() + finalPath);
    }

    @Override
    @SneakyThrows
    public void download(FileDownloadReqVO reqVO, HttpServletResponse response) {
        FileDO fileDO = fileMapper.selectById(reqVO.getFileId());
        GetObjectResponse fileInputStream = minioClient.getObject(GetObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileDO.getPath())
                .build());
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileDO.getOriginalName(), "UTF-8"));
        IoUtil.copy(fileInputStream, response.getOutputStream());
    }

    @Override
    @SneakyThrows
    public FilePreSignedRespVO preSigned(FilePreSignedReqVO reqVO) {

        String preSignedUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .method(Method.PUT)
                .bucket(minioConfig.getBucketName())
                .object(StrUtil.removePrefix(reqVO.getPath(), "/"))
                .expiry(10, TimeUnit.MINUTES)
                .build());
        return new FilePreSignedRespVO()
                .setPreSignedUrl(preSignedUrl)
                .setAccessUrl(minioConfig.getStaticDomain() + "/" + minioConfig.getBucketName() + "/" + reqVO.getPath());
    }

    @Override
    public void record(FileRecordReqVO reqVO) {
        fileMapper.insert(BeanUtil.copyProperties(reqVO, FileDO.class));
    }
}
